﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace XGIS
{
    public partial class FormXGIS : Form
    {
        /// <summary>
        /// 存储空间点对象
        /// </summary>
        XLayer layer = null;
        XView view = null;
        XLayer bufferLayer = null; // 新增，存储缓冲区图层

        BufferedGraphicsContext backWindow;
        BufferedGraphics backMap;

        public Point MouseDownLocation;
        public Point MouseCurrentLocation;

        public bool MouseZoomIn = false;
        public bool MousePan = false;

        public FormXGIS()
        {
            InitializeComponent();
            this.SetStyle(
                System.Windows.Forms.ControlStyles.UserPaint |
                System.Windows.Forms.ControlStyles.AllPaintingInWmPaint |
                System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer,
                true);
            backWindow = BufferedGraphicsManager.Current;
            view = new XView(new XExtent(new XVertex(0, 0), new XVertex(1, 1)), this.ClientRectangle);
            this.MouseWheel+= new System.Windows.Forms.MouseEventHandler(OnMouseWheel);
        }

        private void OnMouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0)
                view.UpdateExtent(XMapActions.zoomin);
            else
                view.UpdateExtent(XMapActions.zoomout);
            UpdateMap();
        }
        private int ScreenDistance(Point _P1, Point _P2)
        {
            return Math.Abs(_P1.X - _P2.X) + Math.Abs(_P1.Y - _P2.Y);
        }

        private void UpdateMap()
        {
            //先清空之前占用的绘图资源
            if (backMap != null)
            {
                if (backMap.Graphics != null)
                    backMap.Graphics.Dispose();
                backMap.Dispose();
            }
            //初始化绘图资源
            Graphics frontGraphics = CreateGraphics();
            backMap = backWindow.Allocate(frontGraphics, ClientRectangle);
            frontGraphics.Dispose();
            //在背景窗口中绘图
            Graphics graphics = backMap.Graphics;
            graphics.FillRectangle(new SolidBrush(Color.Black), ClientRectangle);
            // 绘制缓冲区图层
            if (bufferLayer != null)
            {
                bufferLayer.Draw(graphics, view);
            }
            // 绘制原图层
            layer.Draw(graphics, view);
            //把绘图内容搬到前端
            Invalidate();
        }

        private void MapExplore(object sender, EventArgs e)
        {
            XMapActions action = XMapActions.zoomin;
            if ((Button)sender == bZoomIn) action = XMapActions.zoomin;
            else if ((Button)sender == bZoomOut) action = XMapActions.zoomout;
            else if ((Button)sender == bMoveUp) action = XMapActions.moveup;
            else if ((Button)sender == bMoveDown) action = XMapActions.movedown;
            else if ((Button)sender == bMoveLeft) action = XMapActions.moveleft;
            else if ((Button)sender == bMoveRight) action = XMapActions.moveright;
            view.UpdateExtent(action);
            UpdateMap();
        }

        private void BOpenShapefile_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Shapefile文件|*.shp";
            openFileDialog.RestoreDirectory = false;
            openFileDialog.FilterIndex = 1;
            openFileDialog.Multiselect = false;
            if (openFileDialog.ShowDialog() != DialogResult.OK) return;
            XShapefile sf = new XShapefile();
            layer = sf.ReadShapefile(openFileDialog.FileName);
            layer.DrawAttributeOrNot = false;
            MessageBox.Show("读入" + layer.FeatureCount() + "个实体");
            view.UpdateExtent(layer.Extent);
            UpdateMap();
        }

        private void BFullExtent_Click(object sender, EventArgs e)
        {
            view.UpdateExtent(layer.Extent);
            UpdateMap();
        }

        private void FormXGIS_MouseClick(object sender, MouseEventArgs e)
        {
            if (layer == null) return;
            XVertex onevertex = view.ToMapVertex(e.Location);
            double mindistance = Double.MaxValue;
            int findid = -1;
            for (int i = 0; i < layer.FeatureCount(); i++)
            {
                double distance = layer.GetFeature(i).Spatial.Centroid.Distance(onevertex);
                if (distance < mindistance)
                {
                    mindistance = distance;
                    findid = i;
                }
            }
            Point neartestFeatureLocation = view.ToScreenPoint(layer.GetFeature(findid).Spatial.Centroid);
            if (ScreenDistance(e.Location, neartestFeatureLocation) < 5)
                MessageBox.Show(findid.ToString());
        }

        private void BOpenAttribute_Click(object sender, EventArgs e)
        {
            FormAttribute form = new FormAttribute(layer);
            form.Show();
        }

        private void BWriteMyFile_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            if (sfd.ShowDialog() != DialogResult.OK) return;
            XMyFile myFile = new XMyFile();
            myFile.WriteFile(layer, sfd.FileName);
            MessageBox.Show("完成");
        }

        private void BReadMyFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() != DialogResult.OK) return;
            XMyFile myFile = new XMyFile();
            layer = myFile.ReadFile(openFileDialog.FileName);
            MessageBox.Show("读入" + layer.FeatureCount() + "个实体");
            view.UpdateExtent(layer.Extent);
            UpdateMap();
        }

        private void FormXGIS_Paint(object sender, PaintEventArgs e)
        {
            if (backMap != null)
            {
                backMap.Render(e.Graphics);
                if (MouseZoomIn)
                {
                    int x = Math.Min(MouseDownLocation.X, MouseCurrentLocation.X);
                    int y = Math.Min(MouseDownLocation.Y, MouseCurrentLocation.Y);
                    int width = Math.Abs(MouseDownLocation.X - MouseCurrentLocation.X);
                    int height = Math.Abs(MouseDownLocation.Y - MouseCurrentLocation.Y);
                    e.Graphics.DrawRectangle(new Pen(Color.Red, 2), x, y, width, height);
                }
                else if (MousePan)
                {
                    e.Graphics.DrawLine(new Pen(Color.Red, 2), MouseDownLocation, MouseCurrentLocation);
                }
            }
        }

        private void FormXGIS_SizeChanged(object sender, EventArgs e)
        {
            if (layer == null) return;
            if (ClientRectangle.Width == 0 || ClientRectangle.Height == 0) return;
            view.UpdateWindowSize(ClientRectangle);
            UpdateMap();
        }

        private void FormXGIS_MouseDown(object sender, MouseEventArgs e)
        {
            MouseDownLocation = e.Location;
            if (e.Button == MouseButtons.Left)
                MouseZoomIn = true;
            else if (e.Button == MouseButtons.Middle)
                MousePan = true;
        }

        private void FormXGIS_MouseMove(object sender, MouseEventArgs e)
        {
            MouseCurrentLocation = e.Location;
            //如果没动
            if (e.Location.X == MouseDownLocation.X && e.Location.Y == MouseDownLocation.Y)
                return;
            //如果是拉框放大
            if (MouseZoomIn||MousePan)
                Invalidate();
        }

        private void FormXGIS_MouseUp(object sender, MouseEventArgs e)
        {
            //没有打开任何图层
            if (layer == null) return;
            //未发生变化
            if (e.Location.X == MouseDownLocation.X && e.Location.Y == MouseDownLocation.Y) return;
            XVertex v1 = view.ToMapVertex(MouseDownLocation);
            XVertex v2 = view.ToMapVertex(e.Location);
            //如果是拉框放大
            if (MouseZoomIn)
            {
                XExtent extent = new XExtent(v1, v2);
                view.UpdateExtent(extent);
                UpdateMap();
            }
            //如果是平移地图
            else if (MousePan)
            {
                view.OffsetCenter(v1, v2);
                UpdateMap();
            }
            MouseZoomIn = MousePan = false;
        }

        private void FormXGIS_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Middle)
            {
                view.UpdateExtent(layer.Extent);
                UpdateMap();
            }
            MouseZoomIn = MousePan = false;
        }

        private void bBuffer_Click(object sender, EventArgs e) 
        {
            if (layer == null)
            {
                MessageBox.Show("请先加载数据");
                return;
            }else if(layer.Features.Count == 0)
            {
                MessageBox.Show("图层没有任何要素,无法创建缓冲区");
                return;
            }else if(layer.Features.Count > 0)
            {
                AddBufferFeatures(); // 生成缓冲区
                MessageBox.Show("缓冲区创建完成");
            }
            UpdateMap(); // 更新地图显示 
        }


        //添加缓冲区方法
        private void AddBufferFeatures()
        {

            bufferLayer = new XLayer("BufferLayer", SHAPETYPE.polygon, new XExtent(new XVertex(0, 0), new XVertex(1, 1)), new List<XField>()); // 初始化缓冲区图层

            foreach (XFeature feature in layer.Features)
            {
                XSpatial spatial = feature.Spatial;
                XAttribute attribute = feature.Attribute;

                if (spatial is XPointSpatial)
                {
                    XPointSpatial point = (XPointSpatial)spatial;
                    XPolygonSpatial buffer = BufferOperations.CreateBufferForPoint(point, 1000, Color.Green);
                    bufferLayer.AddFeature(new XFeature(buffer, CloneAttribute(attribute)));
                }
                else if (spatial is XLineSpatial)
                {
                    XLineSpatial line = (XLineSpatial)spatial;
                    XPolygonSpatial buffer = BufferOperations.CreateBufferForLine(line, 800, Color.Blue);
                    bufferLayer.AddFeature(new XFeature(buffer, CloneAttribute(attribute)));
                }
                else if (spatial is XPolygonSpatial)
                {
                    XPolygonSpatial polygon = (XPolygonSpatial)spatial;
                    XPolygonSpatial buffer = BufferOperations.CreateBufferForPolygon(polygon, 50, Color.Red);
                    bufferLayer.AddFeature(new XFeature(buffer, CloneAttribute(attribute)));
                }
            }
        }



        // 复制属性表的方法
        private XAttribute CloneAttribute(XAttribute attribute)
        {
            XAttribute newAttribute = new XAttribute();
            foreach (object value in attribute.Values)
            {
                newAttribute.AddValue(value);
            }
            return newAttribute;
        }


        

    }
    }

 
